///*=============================================================================
//    Copyright (c) 2001-2010 Joel de Guzman
//
//    Distributed under the Boost Software License, Version 1.0. (See accompanying
//    file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//=============================================================================*/
/////////////////////////////////////////////////////////////////////////////////
////
////  A mini XML-like parser
////
////  [ JDG March 25, 2007 ]   spirit2
////
/////////////////////////////////////////////////////////////////////////////////
//
//#include <boost/config/warning_disable.hpp>
//#include <boost/spirit/include/qi.hpp>
//#include <boost/spirit/include/phoenix_core.hpp>
//#include <boost/spirit/include/phoenix_operator.hpp>
//#include <boost/fusion/include/adapt_struct.hpp>
//#include <boost/variant/recursive_variant.hpp>
//#include <boost/foreach.hpp>
//#include <algorithm>
//
//#include <iostream>
//#include <fstream>
//#include <string>
//#include <vector>
//
//namespace client
//{
//    namespace fusion = boost::fusion;
//    namespace phoenix = boost::phoenix;
//    namespace qi = boost::spirit::qi;
//    namespace ascii = boost::spirit::ascii;
//
//    ///////////////////////////////////////////////////////////////////////////
//    //  Our mini XML tree representation
//    ///////////////////////////////////////////////////////////////////////////
//    struct mini_xml;
//
//    typedef
//        boost::variant<
//            boost::recursive_wrapper<mini_xml>
//          , std::string
//        >
//    mini_xml_node;
//
//    struct mini_xml
//    {
//        std::string name;                           // tag name
//        std::vector<mini_xml_node> children;        // children
//    };
//}
//
//// We need to tell fusion about our mini_xml struct
//// to make it a first-class fusion citizen
//BOOST_FUSION_ADAPT_STRUCT(
//    client::mini_xml,
//    (std::string, name)
//    (std::vector<client::mini_xml_node>, children)
//)
//
//namespace client
//{
//    ///////////////////////////////////////////////////////////////////////////
//    //  Print out the mini xml tree
//    ///////////////////////////////////////////////////////////////////////////
//    int const tabsize = 4;
//
//    void tab(int indent)
//    {
//        for (int i = 0; i < indent; ++i)
//            std::cout << ' ';
//    }
//
//    struct mini_xml_printer
//    {
//        mini_xml_printer(int indent = 0)
//          : indent(indent)
//        {
//        }
//
//        void operator()(mini_xml const& xml) const;
//
//        int indent;
//    };
//
//    struct mini_xml_node_printer : boost::static_visitor<>
//    {
//        mini_xml_node_printer(int indent = 0)
//          : indent(indent)
//        {
//        }
//
//        void operator()(mini_xml const& xml) const
//        {
//            mini_xml_printer(indent+tabsize)(xml);
//        }
//
//        void operator()(std::string const& text) const
//        {
//            tab(indent+tabsize);
//            std::cout << "text: \"" << text << '"' << std::endl;
//        }
//
//        int indent;
//    };
//
//    void mini_xml_printer::operator()(mini_xml const& xml) const
//    {
//        tab(indent);
//        std::cout << "tag: " << xml.name << std::endl;
//        tab(indent);
//        std::cout << '{' << std::endl;
//
//        BOOST_FOREACH(mini_xml_node const& node, xml.children)
//        {
//            boost::apply_visitor(mini_xml_node_printer(indent), node);
//        }
//
//        tab(indent);
//        std::cout << '}' << std::endl;
//    }
//
//    ///////////////////////////////////////////////////////////////////////////
//    //  Our mini XML grammar definition
//    ///////////////////////////////////////////////////////////////////////////
//    //[tutorial_xml2_grammar
//    template <typename Iterator>
//    struct mini_xml_grammar
//      : qi::grammar<Iterator, mini_xml(), qi::locals<std::string>, ascii::space_type>
//    {
//        mini_xml_grammar()
//          : mini_xml_grammar::base_type(xml)
//        {
//            using qi::lit;
//            using qi::lexeme;
//            using ascii::char_;
//            using ascii::string;
//            using namespace qi::labels;
//
//            text %= lexeme[+(char_ - '<')];
//            node %= xml | text;
//
//            start_tag %=
//                    '<'
//                >>  !lit('/')
//                >>  lexeme[+(char_ - '>')]
//                >>  '>'
//            ;
//
//            end_tag =
//                    "</"
//                >>  string(_r1)
//                >>  '>'
//            ;
//
//            xml %=
//                    start_tag[_a = _1]
//                >>  *node
//                >>  end_tag(_a)
//            ;
//        }
//
//        qi::rule<Iterator, mini_xml(), qi::locals<std::string>, ascii::space_type> xml;
//        qi::rule<Iterator, mini_xml_node(), ascii::space_type> node;
//        qi::rule<Iterator, std::string(), ascii::space_type> text;
//        qi::rule<Iterator, std::string(), ascii::space_type> start_tag;
//        qi::rule<Iterator, void(std::string), ascii::space_type> end_tag;
//    };
//    //]
//}
//
/////////////////////////////////////////////////////////////////////////////////
////  Main program
/////////////////////////////////////////////////////////////////////////////////
//int main(int argc, char **argv)
//{
//    char const* filename;
//    if (argc > 1)
//    {
//        filename = argv[1];
//    }
//    else
//    {
//        std::cerr << "Error: No input file provided." << std::endl;
//        return 1;
//    }
//
//    std::ifstream in(filename, std::ios_base::in);
//
//    if (!in)
//    {
//        std::cerr << "Error: Could not open input file: "
//            << filename << std::endl;
//        return 1;
//    }
//
//    std::string storage; // We will read the contents here.
//    in.unsetf(std::ios::skipws); // No white space skipping!
//    std::copy(
//        std::istream_iterator<char>(in),
//        std::istream_iterator<char>(),
//        std::back_inserter(storage));
//
//    typedef client::mini_xml_grammar<std::string::const_iterator> mini_xml_grammar;
//    mini_xml_grammar xml; // Our grammar
//    client::mini_xml ast; // Our tree
//
//    using boost::spirit::ascii::space;
//    std::string::const_iterator iter = storage.begin();
//    std::string::const_iterator end = storage.end();
//    bool r = phrase_parse(iter, end, xml, space, ast);
//
//    if (r && iter == end)
//    {
//        std::cout << "-------------------------\n";
//        std::cout << "Parsing succeeded\n";
//        std::cout << "-------------------------\n";
//        client::mini_xml_printer printer;
//        printer(ast);
//        return 0;
//    }
//    else
//    {
//        std::string::const_iterator some = iter+30;
//        std::string context(iter, (some>end)?end:some);
//        std::cout << "-------------------------\n";
//        std::cout << "Parsing failed\n";
//        std::cout << "stopped at: \": " << context << "...\"\n";
//        std::cout << "-------------------------\n";
//        return 1;
//    }
//}
